﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

namespace ChessServises
{
    public class ChessDAL
    {
        private ChessEntities context = new ChessEntities();

        public Guid CreateUser(string userName)
        {
            Guid userId = Guid.NewGuid();
            User user = new User()
            {
                UserId = userId,
                UserName = userName
            };
            context.Users.AddObject(user);
            context.SaveChanges();
            return userId;
        }

        public void DeleteUser(Guid userId)
        {
            User user = context.Users.FirstOrDefault(u => u.UserId == userId);
            if (user == null)
            {
                throw new ArgumentException("Invalid user id " + userId);
            }

            context.Users.DeleteObject(user);
            context.SaveChanges();
        }

        public void JoinGame(int tableId, Guid userId)
        {
            GameTable table = GetTableById(tableId);
            if (table == null)
            {
                throw new ArgumentException();
            }
            if (table.WhitePlayerId == null)
            {
                table.WhitePlayerId = userId;
            }
            else
            {
                table.BlackPlayerId = userId;
            }
            context.SaveChanges();

        }

        public int CreateGame(Guid userId, Colour colour)
        {
            ChessBoard board = new ChessBoard();

            BinaryFormatter formatter = new BinaryFormatter();
            MemoryStream stream = new MemoryStream();
            formatter.Serialize(stream, board);
            byte[] bytes = stream.ToArray();

            GameTable table = new GameTable()
            {
                Table = bytes,
                LastModified = DateTime.Now
            };
            if (colour == Colour.Black)
            {
                table.BlackPlayerId = userId;
            }
            else
            {
                table.WhitePlayerId = userId;
            }
            context.GameTables.AddObject(table);
            context.SaveChanges();

            return table.TableId;
        }

        public GameTable GetTableById(int tableId)
        {
            GameTable table = context.GameTables.FirstOrDefault(g => g.TableId == tableId);

            return table;
        }

        public void ChangeTable(int tableId, Stream newBoard)
        {
            GameTable table = context.GameTables.FirstOrDefault(g => g.TableId == tableId);
            byte[] bytes = GetStreamBytes(newBoard);
            table.Table = bytes;
            table.LastModified = DateTime.Now;
            context.SaveChanges();
        }


        public List<int> GetTableIds()
        {
            List<int> tableIds = new List<int>();
            foreach (GameTable table in context.GameTables)
            {
                tableIds.Add(table.TableId);
            }
            return tableIds;
        }

        private byte[] GetStreamBytes(Stream stream)
        {
            using (MemoryStream memoryStream = new MemoryStream())
            {
                stream.Position = 0;
                int bytesRead;
                int bufferSize=4*1024;
                byte[] buffer = new byte[bufferSize];
                while ((bytesRead = stream.Read(buffer, 0, bufferSize)) > 0)
                {
                    memoryStream.Write(buffer, 0, bytesRead);
                }

                return memoryStream.ToArray();
            }
        }
    }
}